package commun;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SealedObject;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;



/**
 * 
 * Permet de chiffrer et déchiffrer des paquets.
 * 
 * @author Valentin Brémond
 * 
 * @version 1.0
 *
 */
public class Chiffrement
{
	/**
	 * Stocke la clé.
	 */
	private SecretKey cle;
	
	/**
	 * Stocke l'algorithme de chiffrement.
	 */
	private String algorithme;
	
	/**
	 * Stocke l'instance de l'algorithme.
	 */
	private Cipher cipher;
	
	
	
	// CONSTRUCTEURS
	
	
	
	/**
	 * Constructeur par défaut (privé pour empêcher l'instanciation).
	 */
	@SuppressWarnings ("unused")
	private Chiffrement ()
	{
	}
	
	
	
	/**
	 * Constructeur par valeurs.
	 * 
	 * @param cle La clé à utiliser.
	 * @param algorithme L'algorithme à utiliser.
	 * 
	 * @throws NoSuchPaddingException 
	 * @throws NoSuchAlgorithmException 
	 */
	public Chiffrement (String cle, String algorithme) throws NoSuchAlgorithmException, NoSuchPaddingException
	{
		// On récupère la clé et l'algorithme
		setAlgorithme (algorithme);
		setCle (new SecretKeySpec (cle.getBytes (), this.algorithme));
		
		// On prépare l'algorithme
		cipher = Cipher.getInstance (algorithme);
	}
	
	
	
	// MÉTHODES
	
	
	
	/**
	 * Permet de chiffrer un paquet.
	 * 
	 * @param paquet Le paquet à chiffrer.
	 * 
	 * @return Le paquet chiffré.
	 * 
	 * @throws InvalidKeyException 
	 * @throws IOException 
	 * @throws IllegalBlockSizeException 
	 */
	public SealedObject chiffrer (Paquet paquet) throws InvalidKeyException, IllegalBlockSizeException, IOException
	{	
		// On prépare à chiffrer
		cipher.init (Cipher.ENCRYPT_MODE, this.cle);
		
		// On scelle le paquet et on le renvoie
		return new SealedObject (paquet, cipher);
	}
	
	
	
	/**
	 * Permet de déchiffrer un paquet.
	 * 
	 * @param paquetChiffre Le paquet à déchiffrer.
	 * 
	 * @return Le paquet déchiffré.
	 * 
	 * @throws ClassNotFoundException
	 * @throws IllegalBlockSizeException
	 * @throws BadPaddingException
	 * @throws IOException
	 * @throws InvalidKeyException
	 */
	public Paquet dechiffrer (SealedObject paquetChiffre) throws InvalidKeyException, ClassNotFoundException, IllegalBlockSizeException, BadPaddingException, IOException
	{	
		// On prépare à déchiffrer
		cipher.init (Cipher.DECRYPT_MODE, this.cle);
		
		// On déscelle l'objet et on le renvoie
		return (Paquet) paquetChiffre.getObject (cipher);
	}
	
	
	
	// GETTERS & SETTERS
	
	
	
	@SuppressWarnings ("unused")
	private SecretKey getCle ()
	{
		return cle;
	}

	private void setCle (SecretKey cle)
	{
		this.cle = cle;
	}
	
	public String getAlgorithme ()
	{
		return algorithme;
	}

	private void setAlgorithme (String algorithme)
	{
		this.algorithme = algorithme;
	}
}
